﻿
Partial Public Class fceslite4(Of THREADSAFE As _boolean)
    Partial Private Class cluster4
        Private Shared Function read_int64(ByVal vd As virtdisk,
                                           ByRef start As Int64,
                                           ByRef o As Int64) As Boolean
            Dim bts As bytes = Nothing
            If vd.read(start, SIZEOF_INT64, bts) AndAlso
               convertor.toint64(bts, o) Then
                start += SIZEOF_INT64
                Return True
            Else
                Return False
            End If
        End Function

        Private Shared Function read_checksum(ByVal vd As virtdisk,
                                              ByRef start As Int64) As Boolean
            Dim bts As bytes = Nothing
            If vd.read(start, CHECKSUM_SIZE, bts) AndAlso
               bts = CHECKSUM Then
                start += CHECKSUM_SIZE
                Return True
            Else
                Return False
            End If
        End Function

        Private Sub write_int64(ByVal v As Int64, ByVal offset As Int64)
            Dim b As bytes = Nothing
            b = convertor.tobytes(v)
            assert(b.size() = SIZEOF_INT64)
            If Not vd().write(diskoffset() + offset, b) Then
                raiseError(errorHandle.errorType.exclamation,
                           "failed to write data ", v, " to offset ", offset, ", the data will be lost.")
            End If
        End Sub

        Private Sub write_clusterId()
            write_int64(clusterId(), CLUSTERID_OFFSET)
        End Sub

        Private Sub write_used()
            write_int64(used_raw(), USED_OFFSET)
        End Sub

        Private Sub write_length()
            write_int64(length(), LENGTH_OFFSET)
        End Sub

        Private Sub write_prevClusterId()
            write_int64(prevClusterId(), PREVCLUSTERID_OFFSET)
        End Sub

        Private Sub write_nextClusterId()
            write_int64(nextClusterId(), NEXTCLUSTERID_OFFSET)
        End Sub

        Private Sub write_checksum()
            If Not vd().write(diskoffset() + CHECKSUM_OFFSET, CHECKSUM) Then
                raiseError(errorHandle.errorType.exclamation,
                           "failed to write checksum to offset ", diskoffset() + CHECKSUM_OFFSET)
            End If
        End Sub

        Private Shared Function read_cluster_structure(ByVal vd As virtdisk,
                                                       ByVal diskoffset As Int64,
                                                       ByRef clusterId As Int64,
                                                       ByRef used As Int64,
                                                       ByRef length As Int64,
                                                       ByRef prevClusterId As Int64,
                                                       ByRef nextClusterId As Int64) As Boolean
            Dim start As Int64 = 0
            start = diskoffset
            Return valid_virtdisk(vd) AndAlso
                   valid_diskoffset(diskoffset) AndAlso
 _
                   read_int64(vd, diskoffset, clusterId) AndAlso
                   read_int64(vd, diskoffset, used) AndAlso
                   read_int64(vd, diskoffset, length) AndAlso
                   read_int64(vd, diskoffset, prevClusterId) AndAlso
                   read_int64(vd, diskoffset, nextClusterId) AndAlso
                   read_checksum(vd, diskoffset) AndAlso
 _
                   valid_clusterId(clusterId) AndAlso
                   valid_used(used, length) AndAlso
                   valid_length(length) AndAlso
                   valid_chainClusterId(prevClusterId) AndAlso
                   valid_chainClusterId(nextClusterId) AndAlso
                   valid_used_chainClusterId_combination(used, prevClusterId, nextClusterId) AndAlso
                   end_diskoffset(start, length) <= vd.size()
        End Function

        Private Sub write_cluster_structure()
            write_clusterId()
            write_used()
            write_length()
            write_prevClusterId()
            write_nextClusterId()
            write_checksum()
            vd().fill(diskoffset() + DATA_OFFSET, length())
        End Sub

        Public Function read(ByVal bts As pointer(Of bytes), ByRef ec As eventComb) As Boolean
            assert(Not free())
            Return vd().read4(diskoffset() + DATA_OFFSET, used(), bts, ec)
        End Function

        Public Function delete() As Boolean
            used_raw() = INVALID
            clear_nextClusterId()
            clear_prevClusterId()
            assert(free())
            write_used()
            Return True
        End Function

        Public Sub chain_after(ByVal last As cluster4)
            Dim f As Boolean = False
            f = free()
            assert(Not has_prevCluster())
            prevClusterId() = last.clusterId()
            assert(Not last.has_nextCluster())
            last.nextClusterId() = clusterId()
            If f Then
                used_raw() = 0
            End If
            assert(Not free())
        End Sub

        Public Function append(ByVal buff As bytes, ByRef ec As eventComb) As Boolean
            assert(Not buff Is Nothing)
            assert(buff.size() > 0)
            assert(buff.size() + used() <= length())
            Dim writeec As eventComb = Nothing
            ec = chain(as_predict(Function() As Boolean
                                      Return vd.write4(diskoffset() + DATA_OFFSET + used(),
                                                       buff,
                                                       writeec)
                                  End Function),
                       as_eventComb(Function() As eventComb
                                        Return writeec
                                    End Function),
                       as_predict(Function() As Boolean
                                      used_raw() = used() + buff.size()
                                      write_used()
                                      Return True
                                  End Function))
            Return True
        End Function
    End Class
End Class
